
import java.util.ArrayList;

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

/**
 *
 * @author joaera,rco251, julicampagna, giseMontanari
 */
public class Calculadora {

    public Polinomio suma (Polinomio p , Polinomio q){
        if (p.size()==0){
            return q;
        }
        if (q.size()==0){
            return p;
        }
        Polinomio aux = fusionarPol(p,q);
        Polinomio res = new Polinomio();
        int i = 0;
        Termino a = new Termino();
        Termino b = new Termino();
        Termino r = new Termino();
        while (i<aux.size()-1){
            a = aux.get(i);
            b = aux.get(i+1);
            if (a.getExponente() == b.getExponente()){
                r = new Termino(a.getValor()+b.getValor(),a.getExponente());
                res.insertOrd(r);
                i++;
            }
            else{
                res.insertOrd(a);
            }
            i++;
        }
        if (aux.get(aux.size()-1).getExponente() != aux.get(aux.size()-2).getExponente()){
            res.insertOrd(aux.get(aux.size()-1));
        }
        return res;
    }

    public Polinomio resta (Polinomio p , Polinomio q) throws Exception{
        return suma(p,opuesto(q));
    }

    public Polinomio producto(Polinomio p , Polinomio q){
        Polinomio producto= new Polinomio();
        if (p.size()==0){
            return q;
        }
        if (q.size()==0){
            return p;
        }
        Polinomio prod= new Polinomio();
        Termino p3= new Termino();
        Termino p1 = new Termino();
        Termino p2 = new Termino();
        int aux= 0;
        int longP= p.size();
        int i= 0;
        int j= 0;
        while (aux<q.size()){
            while (longP>=0 && i<p.size()){
                p1 = p.get(i);
                p2 = q.get(j);
                p3 = new Termino(p1.getValor()*p2.getValor(),p1.getExponente()+p2.getExponente());
                i++;
                prod.insertOrd(p3);
                longP= longP -1;
                }
            i=0;
            longP=p.size();
            aux++;
            j++;
        }
        prod.ordenarDec();
        int h = 0;
        int v = 0;
        int e = 0;
        ArrayList<Termino> resP = prod.getTerminos();
        while (resP.size()>1){
            p1=resP.get(i);
            v += p1.getValor();
            e = p1.getExponente();
            p2=resP.get(i+1);
             resP.remove(i);
            if (resP.size()==1 && e != p2.getExponente()){
                p3 = new Termino(p2.getValor(),p2.getExponente());
                producto.insertOrd(p3);
            }
            else if (resP.size()==1 && e == p2.getExponente()) {
                v += p2.getValor();
                e = p2.getValor();
                p3 = new Termino(v,e);
                producto.insertOrd(p3);
            }
            if (e!=p2.getExponente()){
                p3 = new Termino(v,e);
                producto.insertOrd(p3);
                e = 0;
                v = 0;
            }
        }
        return producto;
   }

    public Polinomio cociente (Polinomio p , Polinomio q) throws Exception{
        Polinomio rest = new Polinomio();
        Polinomio coc = new Polinomio();
        Polinomio aux = new Polinomio();
        int i=0;
        Termino a= new Termino();
        Termino b= new Termino();
        int c=0;
        if (q.size()==0){
            throw new Exception ("No se puede dividir por el polinomio nulo");
        }
        if (p.size()==0){
            return p;
        }
        p.ordenarDec();
        q.ordenarDec();
        p.completar();
        if (p.grado()>= q.grado()){
            a=p.get(i);
            b=q.get(0);
            while (a.getExponente()>= b.getExponente()){
                a=p.get(i);
                b=q.get(0);
                if (a.getExponente()>= b.getExponente()){
                    Termino d= new Termino((a.getValor() / b.getValor()), (a.getExponente() - b.getExponente()));
                    coc.insertOrd(d);
                    Polinomio e = new Polinomio();
                    e.insertOrd(d);
                    aux=producto(e,q);
                    rest=resta(p,aux);
                    p=rest;//actualizo el polinomio p
                    i++;
                }
            }
        return coc;
        }
        else {
            throw new Exception ("El grado del divisor es mas grande que el grado del dividendo");
        }
    }

    public Polinomio cocienteRuffini (Polinomio p , Polinomio q) throws Exception{
        if (!esPosibleRuffini(p,q)){
            throw new Exception("No es posible aplicar el metodo de Ruffini");
        }
        ArrayList<Integer> coef = p.getCoeficientes();
        ArrayList<Integer> res = new ArrayList<Integer>();
        int r = (-1)*q.getValorDelExp(0);
        int aux = coef.get(0);
        res.add(aux);
        int i = 1;
        while (i<p.size()-1){
            System.out.println(res.get(i-1) + " * " + r + " + " + coef.get(i));
            aux = res.get(i-1) * r + coef.get(i);
            res.add(aux);
            i++;
        }
        Polinomio cociente = new Polinomio(res);
        return cociente;
    }

    public boolean esPosibleRuffini (Polinomio p , Polinomio q){
        return (q.grado()==1) && (q.getValorDelExp(0)!=0);
    }

    private Polinomio fusionarPol (Polinomio p, Polinomio q){
        int i = 0;
        p.ordenarDec();
        while (i<q.size()){
            p.insertOrd(q.get(i));
            i++;
        }
        return p;
    }

    public Polinomio opuesto (Polinomio p) throws Exception{
        int i = 0;
        Termino r = new Termino();
        Polinomio res = new Polinomio();
        while (i<p.size()){
            r.setValor(p.get(i).getValor()*(-1));
            res.addTermPolinomio(r.getValor(), p.get(i).getExponente());
            i++;
        }
        return res;
    }
}